﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Data;

namespace bChatServerComm
{
    public class CommunicationMaster
    {

        #region fields

        static NetTcpBinding Binding;
        static ServiceHost SrvHost;
        static List<Connection> ConnList = new List<Connection>();

        #endregion

        #region public methods

        public static bool Init(string InterfacePort)
        {
            try
            {
                Uri addr = new Uri("net.tcp://localhost:" + InterfacePort);

                Binding = new NetTcpBinding();

                SrvHost = new ServiceHost(typeof(bChatService), addr);
                Binding.Security.Mode = SecurityMode.None; //ehm
                SrvHost.AddServiceEndpoint(typeof(IChatService), Binding, addr);

                SrvHost.Open();

                Notify("Init", "Service started at " + DateTime.Now.ToString(), null, "Notify", null);

                return true;

            }
            catch (Exception ex)
            {
                Notify("Init", "Service startup failed ;" + DateTime.Now.ToString(), null, "Fatal error", ex);

                return false;
                //log
            }
        }




        #endregion


        #region class-only methods

        private static Guid GetConnectionID(OperationContext Callback)
        {
            var res = ConnList.Where(a => a.Callback == Callback).FirstOrDefault();

            if (res != null)
            {
                Guid guid = Guid.NewGuid();

                Connection output = new Connection { Callback = Callback, ID = guid };

                ConnList.Add(output);

                Notify("GetConnectionID", "Incoming connection cid=" + guid.ToString() + "; Address: " + Callback.Channel.RemoteAddress.ToString(), guid, "Notify", null);

                return guid;
            }

            return res.ID;

        }

        private static OperationContext GetCallbackContext(Guid ConnectionID)
        {
            return ConnList.Where(a => a.ID == ConnectionID).Select(a=> a.Callback).FirstOrDefault();
        }

        private static void Notify(string Operation, string Comment, Guid? ConnectionID, string Type, Exception Ex)
        {
            CommWrapperNotify(null, new CommWrapperServiceMessageEventArgs
            {
                Comment=Comment,
                ConnectionID = ConnectionID?? null,
                Ex = Ex,
                Operation = Operation,
                Time = DateTime.Now,
                Type = Type
            });
        }

        #endregion


        #region service handles

        internal static void Request_Register(string UserName, string Password, string Email, string Description, OperationContext Callback)
        {
            var guid = GetConnectionID(Callback);
            CommWrapperRequest_Register(null, new Request_RegisterEventArgs
            {
                ConnectionID = guid,
                Description = Description,
                Email = Email,
                Password = Password,
                Time = DateTime.Now,
                UserName = UserName
            });
        }



        #endregion

        #region response handles

        public static void Response_Register(bool Success, List<string> Errors, Guid ConnectionID)
        {
            var context = GetCallbackContext(ConnectionID);

            if (context != null)
            {
                var callback = context.GetCallbackChannel<IChatServiceCallback>();
                callback.Response_Register(Success, Errors);
            }

        }



        #endregion



        #region event declarations

        public static event CommWrapperNotifyHandler CommWrapperNotify;

        public delegate void CommWrapperNotifyHandler(object sender, CommWrapperServiceMessageEventArgs e);

        public static event CommWrapperRegisterHandler CommWrapperRequest_Register;

        public delegate void CommWrapperRegisterHandler(object sender, Request_RegisterEventArgs e);

        #endregion


    }
}
